import os
import re
import random
import pandas as pd
from openai import OpenAI
from typing import List, Dict, Tuple

# --- 用户配置区域 ---

# 请在此处配置你的 CSV 题库文件路径
QUESTION_CSV_FILE = "D:/桌面/模拟题库_GBK.csv"  # 请替换为你的CSV文件路径

# 请在此处配置您的API密钥和基础URL
API_KEY = "sk-faa84a6e39ed4a78a90b49b8fb811bfc"
BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"
MODEL_NAME = "deepseek-v3"  # 您希望使用的模型

# 考试配置
TOTAL_QUESTIONS = 5
TOTAL_SCORE = 50


# --- 程序核心代码 ---

def load_questions_from_csv(file_path: str) -> pd.DataFrame:
    """
    从指定的CSV文件中加载问题和答案，并处理编码问题。
    CSV文件必须包含 'question' 和 'answer' 两列。
    """
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"题库文件不存在：{file_path}")

    encodings_to_try = ['utf-8','utf-8-sig', 'gbk', 'gb2312', 'latin-1']
    for encoding in encodings_to_try:
        try:
            df = pd.read_csv(file_path, encoding=encoding)
            if 'question' not in df.columns or 'answer' not in df.columns:
                # 即使编码正确，但列名不符，也视为失败
                continue
            print(f"成功使用 {encoding} 编码加载题库文件。")
            return df
        except UnicodeDecodeError:
            continue
        except Exception as e:
            raise RuntimeError(f"加载题库文件失败：{e}")

    raise RuntimeError("无法识别题库文件的编码，请确保文件是 UTF-8、GBK 或 GB2312 格式。")


class QuestionGenerator:
    """负责从加载的题库中出题。"""

    def __init__(self, questions_df: pd.DataFrame):
        self.questions_df = questions_df
        if self.questions_df.empty:
            raise ValueError("无法从CSV文件加载问题，请检查文件内容。")
        self.questions_list = self.questions_df.to_dict('records')

    def generate_question(self) -> Tuple[str, str]:
        """从题库中随机抽取一个问题。"""
        if not self.questions_list:
            return "题库为空，无法出题。", ""

        selected_question = random.choice(self.questions_list)

        question = selected_question['question']
        answer = selected_question['answer']

        return question, answer


class ScoringModule:
    """负责对学生答案进行评分。"""


    def __init__(self):
        self.client = OpenAI(
            api_key=API_KEY,
            base_url=BASE_URL,
        )

    def score_answer(self, question: str, reference_answer: str, student_answer: str, max_score: int) -> Tuple[
        int, str]:
        """
        根据参考答案和学生答案，使用LLM进行评分。
        """
        if not student_answer.strip():
            return 0, "答案为空。"


        try:
            prompt = f"""
你是一名资深的大数据领域专家，请根据提供的“参考答案”，对学生对“问题”的“答案”进行客观、公正的评分，并给出详细的反馈。

评分标准：
- 满分{max_score}分。
- 答案的正确性、完整性、深度和逻辑性是主要的评分依据。
- 评分时请严格按照满分{max_score}分进行打分。

问题：{question}
参考答案：{reference_answer}
学生答案：{student_answer}

请按照以下格式输出：
**分数**：[在此处填写分数]
**反馈**：[在此处填写详细反馈]
"""
            response = self.client.chat.completions.create(
                model=MODEL_NAME,
                messages=[{"role": "user", "content": prompt}],
                temperature=0.1,
            )
            llm_response = response.choices[0].message.content.strip()

            score_match = re.search(r'分数.*?：\s*(\d+)', llm_response)
            feedback_match = re.search(r'反馈.*?：\s*(.*)', llm_response, re.DOTALL)

            score = int(score_match.group(1)) if score_match else 0
            feedback = feedback_match.group(1).strip() if feedback_match else "未能生成有效的评分反馈。"

            return score, feedback

        except Exception as e:
            print(f"评分失败：{e}")
            return 0, f"评分系统发生错误，请联系管理员。错误信息：{str(e)}"


# --- 辅助函数 ---

def get_multiline_input(prompt_message: str) -> str:
    """获取多行用户输入。"""
    print(prompt_message, end='')
    lines = []
    while True:
        line = input()
        if not line:
            break
        lines.append(line)
    return '\n'.join(lines)


# --- 主程序入口 ---

def main():
    print("===== 大数据基础知识章节测试系统启动 =====")

    # 1. 从CSV加载问题
    try:
        questions_df = load_questions_from_csv(QUESTION_CSV_FILE)
        question_generator = QuestionGenerator(questions_df)
    except (FileNotFoundError, RuntimeError, ValueError) as e:
        print(f"初始化失败：{e}")
        return

    # 2. 初始化评分模块
    scoring_module = ScoringModule()

    # 3. 考试开始
    total_score = 0
    exam_answers = []

    print("\n===== 考试开始 =====")
    print(f"本次考试共{TOTAL_QUESTIONS}题，每题{TOTAL_SCORE // TOTAL_QUESTIONS}分。")

    # 打乱问题列表以随机出题
    random.shuffle(question_generator.questions_list)

    # 4. 循环出题和评分
    for i in range(TOTAL_QUESTIONS):
        print(f"\n--- 第{i + 1}题 ---")

        question, reference_answer = question_generator.generate_question()

        print(f"**问题**：{question}\n")

        user_answer = get_multiline_input("请输入你的答案（输入空行结束）：")

        print("\n正在评分，请稍候...")
        score, feedback = scoring_module.score_answer(question, reference_answer, user_answer,
                                                      TOTAL_SCORE // TOTAL_QUESTIONS)

        total_score += score
        exam_answers.append({
            "question": question,
            "answer": user_answer,
            "score": score,
            "feedback": feedback
        })

        print(f"\n**得分**：{score}/{TOTAL_SCORE // TOTAL_QUESTIONS}分")
        print(f"**反馈**：\n{feedback}")

    # 5. 考试结束，输出总分和详情
    print("\n\n===== 考试结束 =====")
    print(f"您的总得分：{total_score} / {TOTAL_SCORE}分")

    print("\n--- 考试详情 ---")
    for i, item in enumerate(exam_answers):
        print(f"\n第{i + 1}题：")
        print(f"问题：{item['question']}")
        print(f"你的答案：\n{item['answer']}")
        print(f"得分：{item['score']}/{TOTAL_SCORE // TOTAL_QUESTIONS}分")
        print(f"反馈：\n{item['feedback']}")

    print("\n考试系统已退出。")


if __name__ == "__main__":
    main()